﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using SupermarketSalesModel;
using System.Xml.Serialization;
using System.IO;
using pe.edu.pucp.lp2.sales.dao;

namespace SupermarketSalesController
{


    public class DBConnection
    {
        public static int dbType = DAOFactory.SQLSERVER;
    }
    [Serializable]
    public class ProductsDB
    {
        DAOFactory daoFactory = null;
        DAOProduct daoProduct = null;


        //private List<Product> productList = new List<Product>();
     

        public List<Product> Values
        {
            get { return daoProduct.queryAll(); }
        }

        public void Add(Product p)
        {
            daoProduct.add(p);
        }
        public int Count
        {
            get { return daoProduct.count(); }
        }

        public void Delete(int i)
        {
            daoProduct.delete(i);
        }

        public void Update( Product p)
        {
            daoProduct.update(p);
        }

        public Product queryById(int productId)
        {
            return daoProduct.queryById(productId);
        }

        public ProductsDB() {
            daoFactory = DAOFactory.getDAOFactory(DBConnection.dbType);
            daoProduct = daoFactory.getDAOProduct();
        }
    }

    [Serializable]
    public class ClientsDB
    {
        DAOFactory daoFactory = null;
        DAOClient daoClient = null;

        public List<Client> Values
        {
            get { return daoClient.queryAll(); }
        }

        public void Add(Client c)
        {
            daoClient.add(c);
        }
        public int Count
        {
            get { return daoClient.count(); }
        }
        public void Delete(String i)
        {
            daoClient.delete(i);
        }
        public void Update(Client c)
        {
            daoClient.update(c);
        }

        public Client queryById(int id)
        {
            return daoClient.queryById(id);
        }

        public Client queryByIdCard(String idCard)
        {
            return daoClient.queryByIdCard(idCard);
        }

        public ClientsDB()
        {
            daoFactory = DAOFactory.getDAOFactory(DBConnection.dbType);
            daoClient = daoFactory.getDAOClient();
        }

    }

    [Serializable]
    public class SaleDB
    {
        DAOFactory daoFactory = null;
        DAOSale daoSale = null;

        public void Add(Sale p)
        {
            daoSale.add(p);
        }
        public int Count
        {
            get { return daoSale.count(); }
        }
        public void Delete(int i)
        {
            daoSale.update(i, 0);
        }

        public Sale queryById(int idSale)
        {
            return daoSale.queryById(idSale);
        }

        public SaleDB()
        {
            daoFactory = DAOFactory.getDAOFactory(DBConnection.dbType);
            daoSale = daoFactory.getDAOSale();
        }


    }

    [Serializable]
    public class CashRegisterDB
    {
        DAOFactory daoFactory = null;
        DAOCashRegister daoCashRegister = null;
        //private List<CashRegister> crList = new List<CashRegister>();
        /*
        public CashRegister this[int i]
        {
            get
            {
                return crList[i];
            }
            set
            {
                crList[i] = value;
            }
        }
        */

        public List<CashRegister> Values
        {
            get { return daoCashRegister.queryAll(); }
        }

        public void Add(CashRegister cr)
        {
            daoCashRegister.add(cr);
        }
        public int Count
        {
            get { return daoCashRegister.count(); }
        }
        public void Delete(int i)
        {
            daoCashRegister.delete(i);
        }

        public CashRegisterDB()
        {
            daoFactory = DAOFactory.getDAOFactory(DBConnection.dbType);
            daoCashRegister = daoFactory.getDAOCashRegister();
        }

        public CashRegister queryById(int id)
        {
            return daoCashRegister.queryById(id);
        }
    }

    [Serializable]
    public class SalesclerkDB
    {
        DAOFactory daoFactory = null;
        DAOSalesclerk daoSalesclerk = null;
        /*private List<Salesclerk> scList = new List<Salesclerk>();
        public Salesclerk this[int i]
        {
            get
            {
                return scList[i];
            }
            set
            {
                scList[i] = value;
            }
        }
        **/
        public List<Salesclerk> Values
        {
            get { return daoSalesclerk.queryAll(); }
        }

        public void Add(Salesclerk sc)
        {
            daoSalesclerk.add(sc);
        }
        public int Count
        {
            get { return daoSalesclerk.count(); }
        }
        public void Delete(int i)
        {
            daoSalesclerk.delete(i);
        }

        public Salesclerk queryById(int SalesclerkId)
        {
            return daoSalesclerk.queryById(SalesclerkId);
        }

        public SalesclerkDB()
        {
            daoFactory = DAOFactory.getDAOFactory(DBConnection.dbType);
            daoSalesclerk = daoFactory.getDAOSalesclerk();
        }

    }

    [Serializable]
    public class CreditNoteDB
    {
        DAOFactory daoFactory = null;
        DAOCreditNote daoCreditNote = null;

        /*
        private List<CreditNote> cnList = new List<CreditNote>();
        public CreditNote this[int i]
        {
            get
            {
                return cnList[i];
            }
            set
            {
                cnList[i] = value;
            }
        }
         * */

        public List<CreditNote> Values
        {
            get { return daoCreditNote.queryAll(); }
        }

        public void Add(CreditNote p)
        {
            daoCreditNote.add(p);
        }
        public int Count
        {
            get { return daoCreditNote.count(); }
        }
        public void Delete(int i)
        {
            daoCreditNote.delete(i);
        }

        public CreditNote getCreditNoteById(int id)
        {
            return daoCreditNote.queryById(id);
        }

        public CreditNoteDB()
        {
            daoFactory = DAOFactory.getDAOFactory(DBConnection.dbType);
            daoCreditNote = daoFactory.getDAOCreditNote();
        }

    }

    [Serializable]
    public class CNDetailDB
    {


        DAOFactory daoFactory = null;
        DAOCNDetail daoCNDetail = null;

        public CNDetailDB(){
            daoFactory = DAOFactory.getDAOFactory(DBConnection.dbType);
            daoCNDetail = daoFactory.getDAOCNDetail();
        }

        private List<CNDetail> cnList = new List<CNDetail>();

        public List<CNDetail> Values
        {
            get { return daoCNDetail.queryAll(); }
        }


        public List<CNDetail> getCNDofCN(int cnId)
        {
            return daoCNDetail.queryAllbyCN(cnId);
        }
        

        public void Add(CNDetail cn)
        {
            daoCNDetail.add(cn);
        }
        public int Count
        {
            get { return daoCNDetail.count(); }
        }
        public void Delete(int i)
        {
            daoCNDetail.delete(i);
        }

        public void Update(CNDetail cnd)
        {
            daoCNDetail.update(cnd);
        }

        public CNDetail queryByCN(int cnId)
        {
            return daoCNDetail.queryByCN(cnId);
        }

    }

    [Serializable]
    public class PromotionDB
    {
        DAOFactory daoFactory = null;
        DAOPromotion daoPromotion = null;


        //private List<Product> productList = new List<Product>();


        public List<Promotion> Values
        {
            get { return daoPromotion.queryAll(); }
        }

        public void Add(Promotion p)
        {
            daoPromotion.add(p);
        }
        public int Count
        {
            get { return daoPromotion.count(); }
        }

        public void Delete(int i)
        {
            daoPromotion.delete(i);
        }

        public void Update(Promotion p)
        {
            daoPromotion.update(p);
        }

        public Promotion queryById(int id)
        {
            return daoPromotion.queryById(id);
        }

        public PromotionDB()
        {
            daoFactory = DAOFactory.getDAOFactory(DBConnection.dbType);
            daoPromotion = daoFactory.getDAOPromotion();
        }
    }

    public class ProductxPromotionDB
    {
        DAOFactory daoFactory = null;
        DAOProductxPromotion daoProductxPromotion = null;


        //private List<Product> productList = new List<Product>();


        public List<ProductxPromotion> Values
        {
            get { return daoProductxPromotion.queryAll(); }
        }

        public void Add(ProductxPromotion p)
        {
            daoProductxPromotion.add(p);
        }
        public int Count
        {
            get { return daoProductxPromotion.count(); }
        }

        public void Delete(int i)
        {
            daoProductxPromotion.delete(i);
        }

        public void Update(ProductxPromotion p)
        {
            daoProductxPromotion.update(p);
        }

        public ProductxPromotion queryById(int id)
        {
            return daoProductxPromotion.queryById(id);
        }

        public ProductxPromotionDB()
        {
            daoFactory = DAOFactory.getDAOFactory(DBConnection.dbType);
            daoProductxPromotion = daoFactory.getDAOProductxPromotion();
        }
    }


    public class SalesManager
    {
        //private static List<Product> productList = new List<Product>();
        static ProductsDB products = new ProductsDB();
        //private static List<Client> clientList = new List<Client>();
        static ClientsDB clients = new ClientsDB();
        //private static List<CashRegister> crList = new List<CashRegister>();
        static CashRegisterDB cashRegisters = new CashRegisterDB();
        //private static List<Sale> saleList = new List<Sale>();
        static SaleDB sales = new SaleDB();
        //private static List<Salesclerk> salesclerkList = new List<Salesclerk>();
        static SalesclerkDB salesClerks = new SalesclerkDB();
        //private static List<CreditNote> cnList = new List<CreditNote>();
        static CreditNoteDB creditNotes = new CreditNoteDB();

        static CNDetailDB cnDetails = new CNDetailDB();
        /*SERIALIZACION DE CLIENTES*/
        public static void PersistClientsDB()
        {
            XmlSerializer writer = new XmlSerializer(typeof(ClientsDB));
            TextWriter file = new StreamWriter("ClientsDB.xml");
            writer.Serialize(file, clients);
            file.Close();
        }
        public static void ReloadClientsDB()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(ClientsDB));
            FileStream fs = new FileStream("ClientsDB.xml", FileMode.Open);
            clients = (ClientsDB)serializer.Deserialize(fs);
            fs.Close();

        }

        /*SERIALIZACION DE LA VENTA*/
        public static void PersistSaleDB()
        {          
            XmlSerializer writer = new XmlSerializer(typeof(SaleDB));
            TextWriter file = new StreamWriter("SaleDB.xml");
            writer.Serialize(file, sales);
            file.Close();
        }
        public static void ReloadSaleDB()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(SaleDB));
            FileStream fs = new FileStream("SaleDB.xml", FileMode.Open);
            sales = (SaleDB)serializer.Deserialize(fs);
            fs.Close();

        }

        /*SERIALIZACION DE PRODUCTOS*/
        public static void PersistProductsDB()
        {
            XmlSerializer writer = new XmlSerializer(typeof(ProductsDB));
            TextWriter file = new StreamWriter("ProductsDB.xml");
            writer.Serialize(file, products);
            file.Close();
        }
        public static void ReloadProductsDB()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(ProductsDB));
            FileStream fs = new FileStream("ProductsDB.xml", FileMode.Open);
            products = (ProductsDB)serializer.Deserialize(fs);
            fs.Close();

        }


        /*SERIALIZACION DE CAJA*/
        public static void PersistCashRegisterDB()
        {
            XmlSerializer writer = new XmlSerializer(typeof(CashRegisterDB));
            TextWriter file = new StreamWriter("CashRegisterDB.xml");
            writer.Serialize(file, cashRegisters);
            file.Close();
        }
        public static void ReloadCashRegisterDB()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(CashRegisterDB));
            FileStream fs = new FileStream("CashRegisterDB.xml", FileMode.Open);
            cashRegisters = (CashRegisterDB)serializer.Deserialize(fs);
            fs.Close();

        }

        /*SERIALIZACION DE CAJERO*/
        public static void PersistClerkDB()
        {
            XmlSerializer writer = new XmlSerializer(typeof(SalesclerkDB));
            TextWriter file = new StreamWriter("SalesclerkDB.xml");
            writer.Serialize(file, salesClerks);
            file.Close();
        }
        public static void ReloadClerkDB()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(SalesclerkDB));
            FileStream fs = new FileStream("SalesclerkDB.xml", FileMode.Open);
            salesClerks = (SalesclerkDB)serializer.Deserialize(fs);
            fs.Close();
        }

        /*SERIALIZACION DE NOTA DE CREDITO*/
        public static void PersistCreditNoteDB()
        {
            XmlSerializer writer = new XmlSerializer(typeof(CreditNoteDB));
            TextWriter file = new StreamWriter("CreditNoteDB.xml");
            writer.Serialize(file, creditNotes);
            file.Close();
        }
        public static void ReloadCreditNoteDB()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(CreditNoteDB));
            FileStream fs = new FileStream("CreditNoteDB.xml", FileMode.Open);
            creditNotes = (CreditNoteDB)serializer.Deserialize(fs);
            fs.Close();

        }


        /*PRODUCTS*/
        public static double getDescuento(Sale s)
        {
            double desc = 0;
            List<SalesDetail> detalles = s.Details;

            Client c = s.Client;
            for (int i = 0; i < detalles.Count ; i++)
            {
                Product p = detalles[i].Product;
                List<ProductxPromotion> promociones = p.Promociones;

                for (int j = 0; j < promociones.Count; j++)
                {
                    if (promociones[j].Estado == 1)
                    {
                        if (promociones[j].Promotion.NecessaryPoints <= c.Points)
                        {
                            desc += p.BasePrice * promociones[j].Promotion.PorcDesc;
                            c.Points -= promociones[j].Promotion.NecessaryPoints;
                        }
                        
                    }
                }
               
            }
            //updateClient;         ACTUALIZAR PUNTOS DEL CLIENTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                return desc;
        }

        public static void addProduct(Product p)
        {
            products.Add(p);
        }

        public static void updateProduct(Product p)
        {
            products.Update(p);
        }

        public static Product getProductbyId(int id){
            return products.queryById(id);
        }

        public static List<Product> getAllProducts()
        {
            return products.Values;
        }


        public static void deleteProduct(int id)
        {
            products.Delete(id);
        }

        public static int getSizeProduct()
        {
            return products.Count;
        }

        /*CLIENTS*/

        public static void addClient(Client c)
        {
            clients.Add(c);
        }

        public static void updateProduct(Client c)
        {
            clients.Update(c);
        }

        public static Client getClientbyIdCard(String idCard)
        {
            return clients.queryByIdCard(idCard);
        }

        public static Client getClientbyId(int id)
        {
            return clients.queryById(id);
        }

        public static List<Client> getAllClients()
        {
            return clients.Values;
        }

        public static void deleteClient(String idClient)
        {
            clients.Delete(idClient);
        }

        public static int getSizeClient()
        {
            return clients.Count;
        }

        /*CASH REGISTER*/

        public static void addCr(CashRegister cr)
        {
            cashRegisters.Add(cr);
        }

        public static CashRegister getCRbyId(int id)
        {
            return cashRegisters.queryById(id);
        }

        public static List<CashRegister> getAllCashRegisters()
        {
            return cashRegisters.Values;
        }

        public static void deleteCashRegister(int id)
        {
            cashRegisters.Delete(id);
        }

        /*SALES*/

        public static void addSale(Sale s)
        {
            sales.Add(s);
        }

        public static Sale getSaleById(int id)
        {
            return sales.queryById(id);
        }

        public static void deleteSale(int id)
        {
            sales.Delete(id);
        }

        public static int getSizeSale()
        {
            return sales.Count;
        }

        /*SALESCLERKS*/

        public static void addSalesclerk(Salesclerk sc)
        {
            salesClerks.Add(sc);
        }

        public static Salesclerk getSalesclerkbyId(int id)
        {
            return salesClerks.queryById(id);
        }

        public static List<Salesclerk> getAllSalesclerks()
        {
            return salesClerks.Values;
        }

        public static void deleteSalesclerk(int id)
        {
            salesClerks.Delete(id);
        }

        /*CREDIT NOTES*/

        public static void addCreditNote(CreditNote cn)
        {
            creditNotes.Add(cn);
        }

        public static CreditNote getCreditNoteById(int id)
        {
            return creditNotes.getCreditNoteById(id);
        }

        public static List<CreditNote> getAllCreditNotes()
        {
            return creditNotes.Values;
        }

        /* CREDIT NOTE DETAIL (Apoyo a CreditNote) */

        public static void addCNDetail(CNDetail cnd)
        {
            cnDetails.Add(cnd);
        }

        public static CNDetail getCreditNoteDetailById(int id)
        {
            return cnDetails.queryByCN(id);
        }

        public static List<CNDetail> getAllCreditNoteDetails(int cnId)
        {
            return cnDetails.getCNDofCN(cnId);
        }

        public static void updateCNDetail(CNDetail cnd)
        {
            cnDetails.Update(cnd);

        }

        public static void deleteCNDetail(int cndId)
        {
            cnDetails.Delete(cndId);
        }


        static PromotionDB promotions = new PromotionDB();
        static ProductxPromotionDB pxps = new ProductxPromotionDB();

        public static void addPromotion(Promotion p)
        {
            promotions.Add(p);
        }

        public static void updatePromotion(Promotion p)
        {
            promotions.Update(p);
        }

        public static Promotion getPromotionById(int id)
        {
            return promotions.queryById(id);
        }

        public static List<Promotion> getAllPromotions()
        {
            return promotions.Values;
        }

        /*
       public static void deletePromotion(int id)
       {
           promotions.Delete(id);
       }
          */
        public static int getSizePromotion()
        {
            return promotions.Count;
        }
        /***********************************/
        public static void addProductxPromotion(ProductxPromotion p)
        {
            pxps.Add(p);
        }

        public static void updateProductxPromotion(ProductxPromotion p)
        {
            pxps.Update(p);
        }

        public static ProductxPromotion getProductxPromotionById(int id)
        {
            return pxps.queryById(id);
        }

        public static List<ProductxPromotion> getAllProductxPromotion()
        {
            return pxps.Values;
        }

        /*
       public static void deletePromotion(int id)
       {
           promotions.Delete(id);
       }
          */
        public static int getSizeProductxPromotion()
        {
            return pxps.Count;
        }  

   
    }
}
